home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 22 / Cream of the Crop 22.iso / math / ast53src.zip / ASTROLOG.C < prev    next >
C/C++ Source or Header  |  1996-09-29  |  49KB  |  1,868 lines

  1. /*
  2. ** Astrolog (Version 5.30) File: astrolog.c
  3. **
  4. ** IMPORTANT NOTICE: The graphics database and chart display routines
  5. ** used in this program are Copyright (C) 1991-1996 by Walter D. Pullen
  6. ** (Astara@msn.com, http://www.magitech.com/~cruiser1/astrolog.htm).
  7. ** Permission is granted to freely use and distribute these routines
  8. ** provided one doesn't sell, restrict, or profit from them in any way.
  9. ** Modification is allowed provided these notices remain with any
  10. ** altered or edited versions of the program.
  11. **
  12. ** The main planetary calculation routines used in this program have
  13. ** been Copyrighted and the core of this program is basically a
  14. ** conversion to C of the routines created by James Neely as listed in
  15. ** Michael Erlewine's 'Manual of Computer Programming for Astrologers',
  16. ** available from Matrix Software. The copyright gives us permission to
  17. ** use the routines for personal use but not to sell them or profit from
  18. ** them in any way.
  19. **
  20. ** The PostScript code within the core graphics routines are programmed
  21. ** and Copyright (C) 1992-1993 by Brian D. Willoughby
  22. ** (brianw@sounds.wa.com). Conditions are identical to those above.
  23. **
  24. ** The extended accurate ephemeris databases and formulas are from the
  25. ** calculation routines in the program "Placalc" and are programmed and
  26. ** Copyright (C) 1989,1991,1993 by Astrodienst AG and Alois Treindl
  27. ** (alois@azur.ch). The use of that source code is subject to
  28. ** regulations made by Astrodienst Zurich, and the code is not in the
  29. ** public domain. This copyright notice must not be changed or removed
  30. ** by any user of this program.
  31. **
  32. ** Initial programming 8/28,30, 9/10,13,16,20,23, 10/3,6,7, 11/7,10,21/1991.
  33. ** X Window graphics initially programmed 10/23-29/1991.
  34. ** PostScript graphics initially programmed 11/29-30/1992.
  35. ** Last code change made 9/22/1996.
  36. */
  37.  
  38. #include "astrolog.h"
  39.  
  40.  
  41. /*
  42. ******************************************************************************
  43. ** Program Dispatch Procedures.
  44. ******************************************************************************
  45. */
  46.  
  47. /* Initialize the Ansi color arrays with the color to print each object in. */
  48.  
  49. void InitColors()
  50. {
  51.   int i;
  52.  
  53.   kObjA[0] = kElemA[eEar];
  54.   for (i = 1; i <= 10; i++)
  55.     kObjA[i] = kSignA(ruler1[i]);
  56.   for (i = 11; i <= 15; i++)
  57.     kObjA[i] = kMainA[8];
  58.   for (i = 16; i <= 20; i++)
  59.     kObjA[i] = kMainA[6];
  60.   for (i = 1; i <= cSign; i++)
  61.     kObjA[cuspLo+i-1] = kSignA(i);
  62.   for (i = uranLo; i <= uranHi; i++)
  63.     kObjA[i] = kRainbowA[7];
  64.   for (i = starLo; i <= starHi; i++)
  65.     kObjA[i] = rStarBright[i-oNorm] < 1.0 ? kRainbowA[2] : kMainA[4];
  66. }
  67.  
  68.  
  69. /* This is the dispatch procedure for the entire program. After all the   */
  70. /* command switches have been processed, this routine is called to        */
  71. /* actually call the various routines to generate and display the charts. */
  72.  
  73. void Action()
  74. {
  75.   char sz[cchSzDef];
  76.   int i;
  77.  
  78. #ifdef WIN
  79.   is.fMult = fFalse;    /* Cleared here because no InitVariables routine. */
  80. #endif
  81.   is.fSzPersist = is.fNoEphFile = fFalse;
  82.   is.cchRow = 0;
  83.   AnsiColor(kDefault);
  84.   InitColors();
  85.   if (fSouthNode) {
  86.     szObjName[oSou] = "S.Node";
  87. #ifdef INTERPRET
  88.     szMindPart[oSou] =
  89.       "karmic past, and area of experience but little growth";
  90. #endif
  91.     ruler1[oSou] = sLeo;
  92.   }
  93.   szAspectAbbrev[aCon] = us.fParallel ? "Par" : "Con";
  94.   szAspectAbbrev[aOpp] = us.fParallel ? "CPr" : "Opp";
  95.  
  96.   /* First let's adjust the restriction status of the cusps, uranians, and */
  97.   /* fixed stars based on whether -C, -u, and -U switches are in effect.   */
  98.  
  99.   if (!us.fCusp)
  100.     for (i = cuspLo; i <= cuspHi; i++)
  101.       ignore[i] = ignore2[i] = fTrue;
  102.   if (!us.fUranian)
  103.     for (i = uranLo; i <= uranHi; i++)
  104.       ignore[i] = ignore2[i] = fTrue;
  105.   if (!us.nStar)
  106.     for (i = starLo; i <= starHi; i++)
  107.       ignore[i] = ignore2[i] = fTrue;
  108.  
  109.   /* If the -os switch is in effect, open a file and set a global to */
  110.   /* internally 'redirect' all screen output to.                     */
  111.  
  112.   if (is.szFileScreen) {
  113.     is.S = fopen(is.szFileScreen, "w");
  114.     if (is.S == NULL) {
  115.       sprintf(sz, "File %s can not be created.", is.szFileScreen);
  116.       PrintError(sz);
  117.       is.S = stdout;
  118.     }
  119.   } else
  120.     is.S = stdout;
  121.  
  122.   if (FPrintTables())    /* Print out any generic tables specified.        */
  123.     return;              /* If nothing else to do, we can exit right away. */
  124.   if (is.fMult) {
  125.     PrintL2();
  126.     is.fMult = fFalse;
  127.   }
  128.  
  129.   /* If -+ or -- switches in effect, then add the specified delta value to */
  130.   /* the date and use that as a new date before proceeding to make chart.  */
  131.  
  132.   if (us.dayDelta != 0) {
  133.     is.JD = (real)MdyToJulian(MM, DD+us.dayDelta, YY);
  134.     JulianToMdy(is.JD, &MM, &DD, &YY);
  135.   }
  136.  
  137.   /* Here we either do a normal chart or some kind of relationship chart. */
  138.  
  139.   if (!us.nRel) {
  140. #ifndef WIN
  141.     /* If chart info not in memory yet, then prompt the user for it. */
  142.     if (!is.fHaveInfo && !FInputData(szTtyCore))
  143.       return;
  144.     CastChart(fTrue);
  145. #else
  146.     if (wi.fCast) {
  147.       wi.fCast = fFalse;
  148.       CastChart(fTrue);
  149.     }
  150. #endif
  151.     ciMain = ciCore;
  152.   } else
  153.     CastRelation();
  154. #ifndef WIN
  155.   ciSave = ciMain;
  156. #endif
  157.  
  158. #ifdef GRAPH
  159.   if (us.fGraphics)         /* If any of the X window switches in effect, */
  160.     FActionX();             /* then go make a graphics chart...           */
  161.   else
  162. #endif
  163.     PrintChart(is.fProgress);    /* Otherwise print chart on text screen. */
  164.  
  165.   if (us.fWriteFile)        /* If -o switch in effect, then write */
  166.     FOutputData();          /* the chart information to a file.   */
  167.  
  168.   if (is.S != stdout) /* If we were internally directing chart display to a */
  169.     fclose(is.S);     /* file as with the -os switch, close it here.        */
  170.  
  171.   if (grid) {
  172.     DeallocateFar(grid);
  173.     grid = NULL;
  174.   }
  175. }
  176.  
  177.  
  178. #ifndef WIN
  179. /* Reset a few variables to their default values they have upon startup of */
  180. /* the program. We don't reset all variables, just the most volatile ones. */
  181. /* This is called when in the -Q loop to reset things like which charts to */
  182. /* display, but leave setups such as object restrictions and orbs alone.   */
  183.  
  184. void InitVariables()
  185. {
  186.   us.fInterpret = us.fProgress = is.fHaveInfo = is.fMult = fFalse;
  187.   us.nRel = us.dayDelta = 0;
  188.   is.szFileScreen = NULL;
  189.   ClearB((lpbyte)&us.fListing,
  190.     (int)((lpbyte)&us.fLoop - (lpbyte)&us.fListing));
  191. }
  192. #endif
  193.  
  194.  
  195. /*
  196. ******************************************************************************
  197. ** Command Switch Procedures.
  198. ******************************************************************************
  199. */
  200.  
  201. /* Given a string representing a command line (e.g. a macro string), go    */
  202. /* parse it into its various switches and parameters, then go process them */
  203. /* and change program settings. Basically a wrapper for other functions.   */
  204.  
  205. bool FProcessCommandLine(szLine)
  206. char *szLine;
  207. {
  208.   char szCommandLine[cchSzMax], *rgsz[MAXSWITCHES];
  209.   int argc, cb, fT;
  210.  
  211.   if (szLine == NULL)
  212.     return fTrue;
  213.   if (Mon != -1)
  214.     ciCore = ciMain;
  215.   cb = CchSz(szLine)+1;
  216.   CopyRgb((byte *)szLine, (byte *)szCommandLine, cb);
  217.   argc = NParseCommandLine(szCommandLine, rgsz);
  218.   fT = FProcessSwitches(argc, rgsz);
  219.   ciMain = ciCore;
  220.   return fT;
  221. }
  222.  
  223.  
  224. /* Given string representing a command line, convert it to an "argv" format */
  225. /* of an array of strings, one for each switch or parameter, i.e. exactly   */
  226. /* like the format of the command line as given when the program starts.    */
  227.  
  228. int NParseCommandLine(szLine, argv)
  229. char *szLine;
  230. char **argv;
  231. {
  232.   int argc = 1, fSpace = fTrue, fQuote = fFalse;
  233.   char *pch = szLine;
  234.  
  235.   /* Split the entered line up into its individual switch strings. */
  236.   while (*pch >= ' ' || *pch == chTab) {
  237.     if (*pch == ' ' || *pch == chTab) {
  238.       if (fSpace)
  239.         /* Skip over the current run of spaces between strings. */
  240.         ;
  241.       else {
  242.         /* First space after a string, end parameter here. */
  243.         if (!fQuote) {
  244.           *pch = chNull;
  245.           fSpace = fTrue;
  246.         }
  247.       }
  248.     } else {
  249.       if (fSpace) {
  250.         /* First character after run of spaces, begin parameter here. */
  251.         if (argc >= MAXSWITCHES-1) {
  252.           PrintWarning("Too many items - rest of line ignored.");
  253.           break;
  254.         }
  255.         fQuote = (*pch == '"');
  256.         argv[argc++] = pch + fQuote;
  257.         fSpace = fFalse;
  258.       } else
  259.         /* Skip over the current string. */
  260.         if (fQuote && *pch == '"') {
  261.           *pch = chNull;
  262.           fSpace = fTrue;
  263.         }
  264.     }
  265.     pch++;
  266.   }
  267.   argv[0] = szAppNameCore;
  268.   argv[argc] = NULL;         /* Set last string in switch array to Null. */
  269.   return argc;
  270. }
  271.  
  272.  
  273. /* This routine is called by the main program to interactively prompt the  */
  274. /* user for command switches and parameters, entered in the same format as */
  275. /* they would be on a command line. This needs to be called with certain   */
  276. /* systems which don't allow passing of a command line to the program,     */
  277. /* or when -Q is in effect. The result of this routine is returned to the  */
  278. /* main program which then processes it as done with a real command line.  */
  279.  
  280. int NPromptSwitches(line, argv)
  281. char *line, *argv[MAXSWITCHES];
  282. {
  283.   FILE *data;
  284.   char sz[cchSzDef];
  285.  
  286.   data = is.S; is.S = stdout;
  287.   is.cchRow = 0;
  288.   AnsiColor(kWhite);
  289.   sprintf(sz, "** %s version %s ", szAppName, szVersionCore); PrintSz(sz);
  290.   sprintf(sz, "(See '%cHc' switch for copyrights and credits.) **\n",
  291.     chSwitch); PrintSz(sz);
  292.   AnsiColor(kDefault);
  293.   PrintSz("Enter all parameter options below. ");
  294.   sprintf(sz, "(Enter '%cH' for help. Enter '.' to exit.)\n", chSwitch);
  295.   PrintSz(sz);
  296.   is.S = data;
  297.   InputString("Input command line", line);
  298.   PrintL();
  299.   return NParseCommandLine(line, argv);
  300. }
  301.  
  302.  
  303. /* This subprocedure is like FProcessSwitches() below, except that we only */
  304. /* process one switch, which we know to be one of the obscure -Y types.    */
  305.  
  306. int NProcessSwitchesRare(argc, argv, pos, fOr, fAnd, fNot)
  307. int argc, pos;
  308. bool fOr, fAnd, fNot;
  309. char **argv;
  310. {
  311.   int darg = 0, i, j, k;
  312.   real r;
  313.   char ch1, ch2;
  314.   OE oe;
  315.   lpbyte lpb;
  316.   int FPTR *lpn;
  317.   lpreal lpr;
  318. #ifdef INTERPRET
  319.   char *sz;
  320. #endif
  321.  
  322.   ch1 = argv[0][pos+1]; ch2 = argv[0][pos+2];
  323.   switch (argv[0][pos]) {
  324.   case chNull:
  325.     SwitchF(us.fSwitchRare);
  326.     break;
  327.  
  328.   case 'n':
  329.     SwitchF(us.fTrueNode);
  330.     break;
  331.  
  332.   case 'd':
  333.     SwitchF(us.fEuroDate);
  334.     break;
  335.  
  336.   case 't':
  337.     SwitchF(us.fEuroTime);
  338.     break;
  339.  
  340.   case 'C':
  341.     SwitchF(us.fSmartCusp);
  342.     break;
  343.  
  344.   case '8':
  345.     SwitchF(us.fClip80);
  346.     break;
  347.  
  348.   case 'Q':
  349.     if (argc <= 1) {
  350.       ErrorArgc("YQ");
  351.       return tcError;
  352.     }
  353.     i = atoi(argv[1]);
  354.     if (i < 0) {
  355.       ErrorValN("YQ", i);
  356.       return tcError;
  357.     }
  358.     us.nScrollRow = i;
  359.     darg++;
  360.     break;
  361.  
  362.   case 'o':
  363.     SwitchF(us.fWriteOld);
  364.     break;
  365.  
  366.   case 'c':
  367.     SwitchF(us.fHouseAngle);
  368.     break;
  369.  
  370.   case 'z':
  371.     if (argc <= 1) {
  372.       ErrorArgc("Yz");
  373.       return tcError;
  374.     }
  375.     us.lTimeAddition = atol(argv[1]);
  376.     darg++;
  377.     break;
  378.  
  379.   case 'l':
  380.     if (argc <= 1) {
  381.       ErrorArgc("Yl");
  382.       return tcError;
  383.     }
  384.     i = atoi(argv[1]);
  385.     if (!FSector(i)) {
  386.       ErrorValN("Yl", i);
  387.       return tcError;
  388.     }
  389.     SwitchF(pluszone[i]);
  390.     darg++;
  391.     break;
  392.  
  393. #ifdef ARABIC
  394.   case 'P':
  395.     if (argc <= 1) {
  396.       ErrorArgc("YP");
  397.       return tcError;
  398.     }
  399.     i = atoi(argv[1]);
  400.     if (!FBetween(i, -1, 1)) {
  401.       ErrorValN("YP", i);
  402.       return tcError;
  403.     }
  404.     us.nArabicNight = i;
  405.     darg++;
  406.     break;
  407. #endif
  408.  
  409.   case 'b':
  410.     if (argc <= 1) {
  411.       ErrorArgc("Yb");
  412.       return tcError;
  413.     }
  414.     i = atoi(argv[1]);
  415.     if (!FValidBioday(i)) {
  416.       ErrorValN("Yb", i);
  417.       return tcError;
  418.     }
  419.     us.nBioday = i;
  420.     darg++;
  421.     break;
  422.  
  423.   case 'E':
  424.     if (argc <= 17) {
  425.       ErrorArgc("YE");
  426.       return tcError;
  427.     }
  428.     i = NParseSz(argv[1], pmObject);
  429.     if (!FHelio(i)) {
  430.       ErrorValN("YE", i);
  431.       return tcError;
  432.     }
  433.     oe.sma = atof(argv[2]);
  434.     oe.ec0 = atof(argv[3]);  oe.ec1 = atof(argv[4]);  oe.ec2 = atof(argv[5]);
  435.     oe.in0 = atof(argv[6]);  oe.in1 = atof(argv[7]);  oe.in2 = atof(argv[8]);
  436.     oe.ap0 = atof(argv[9]);  oe.ap1 = atof(argv[10]); oe.ap2 = atof(argv[11]);
  437.     oe.an0 = atof(argv[12]); oe.an1 = atof(argv[13]); oe.an2 = atof(argv[14]);
  438.     oe.ma0 = atof(argv[15]); oe.ma1 = atof(argv[16]); oe.ma2 = atof(argv[17]);
  439.     rgoe[IoeFromObj(i)] = oe;
  440.     darg += 17;
  441.     break;
  442.  
  443.   case 'R':
  444.     if (argc <= 2 + (ch1 == 'Z')*2) {
  445.       ErrorArgc("YR");
  446.       return tcError;
  447.     }
  448.     i = NParseSz(argv[1], pmObject); j = NParseSz(argv[2], pmObject);
  449.     if (ch1 == '0') {
  450.       us.fIgnoreSign = i != 0;
  451.       us.fIgnoreDir  = j != 0;
  452.       darg += 2;
  453.       break;
  454.     } else if (ch1 == 'Z') {
  455.       ignorez[0] = i != 0;
  456.       ignorez[1] = j != 0;
  457.       ignorez[2] = atoi(argv[3]) != 0;
  458.       ignorez[3] = atoi(argv[4]) != 0;
  459.       darg += 4;
  460.       break;
  461.     }
  462.     if (!FItem(i)) {
  463.       ErrorValN("YR", i);
  464.       return tcError;
  465.     }
  466.     if (!FItem(j) || j < i) {
  467.       ErrorValN("YR", j);
  468.       return tcError;
  469.     }
  470.     if (argc <= 3+j-i) {
  471.       ErrorArgc("YR");
  472.       return tcError;
  473.     }
  474.     lpb = ch1 == 'T' ? ignore2 : ignore;
  475.     for (k = i; k <= j; k++)
  476.       lpb[k] = atoi(argv[3+k-i]) != 0;
  477.     darg += 3+j-i;
  478.     break;
  479.  
  480.   case 'A':
  481.     if (argc <= 2) {
  482.       ErrorArgc("YA");
  483.       return tcError;
  484.     }
  485.     k = ch1 == 'm' || ch1 == 'd' ? pmObject : pmAspect;
  486.     i = NParseSz(argv[1], k); j = NParseSz(argv[2], k);
  487.     k = ch1 == 'm' || ch1 == 'd' ? cObj : cAspect;
  488.     if (!FBetween(i, 1, k)) {
  489.       ErrorValN("YA", i);
  490.       return tcError;
  491.     }
  492.     if (!FBetween(j, 1, k) || j < i) {
  493.       ErrorValN("YA", j);
  494.       return tcError;
  495.     }
  496.     if (argc <= 3+j-i) {
  497.       ErrorArgc("YA");
  498.       return tcError;
  499.     }
  500.     lpr = ch1 == 'o' ? rAspOrb : (ch1 == 'm' ? rObjOrb :
  501.       (ch1 == 'd' ? rObjAdd : rAspAngle));
  502.     for (k = i; k <= j; k++)
  503.       lpr[k] = atof(argv[3+k-i]);
  504.     darg += 3+j-i;
  505.     break;
  506.  
  507.   case 'j':
  508.     if (argc <= 2 + 2*(ch1 == '0')) {
  509.       ErrorArgc("Yj");
  510.       return tcError;
  511.     }
  512.     if (ch1 == '0') {
  513.       rObjInf[oNorm+1] = atof(argv[1]);
  514.       rObjInf[oNorm+2] = atof(argv[2]);
  515.       rHouseInf[cSign+1]  = atof(argv[3]);
  516.       rHouseInf[cSign+2]  = atof(argv[4]);
  517.       darg += 4;
  518.       break;
  519.     }
  520.     k = ch1 == 'C' ? pmSign : (ch1 == 'A' ? pmAspect : pmObject);
  521.     i = NParseSz(argv[1], k); j = NParseSz(argv[2], k);
  522.     k = ch1 == 'C' ? cSign : (ch1 == 'A' ? cAspect : cObj);
  523.     if (!FBetween(i, 1, k)) {
  524.       ErrorValN("Yj", i);
  525.       return tcError;
  526.     }
  527.     if (!FBetween(j, 1, k) || j < i) {
  528.       ErrorValN("Yj", j);
  529.       return tcError;
  530.     }
  531.     if (argc <= 3+j-i) {
  532.       ErrorArgc("Yj");
  533.       return tcError;
  534.     }
  535.     lpr = ch1 == 'C' ? rHouseInf : (ch1 == 'A' ? rAspInf :
  536.       (ch1 == 'T' ? rTransitInf : rObjInf));
  537.     for (k = i; k <= j; k++)
  538.       lpr[k] = atof(argv[3+k-i]);
  539.     darg += 3+j-i;
  540.     break;
  541.  
  542.   case 'J':
  543.     if (argc <= 3 - (ch1 == '0')) {
  544.       ErrorArgc("YJ");
  545.       return tcError;
  546.     }
  547.     i = NParseSz(argv[1], pmObject);
  548.     if (!FNorm(i)) {
  549.       ErrorValN("YJ", i);
  550.       return tcError;
  551.     }
  552.     j = NParseSz(argv[2], pmSign);
  553.     if (!FBetween(j, 0, cSign)) {
  554.       ErrorValN("YJ", j);
  555.       return tcError;
  556.     }
  557.     if (ch1 != '0') {
  558.       k = NParseSz(argv[3], pmSign);
  559.       if (!FBetween(k, 0, cSign)) {
  560.         ErrorValN("YJ", k);
  561.         return tcError;
  562.       }
  563.       ruler1[i] = j;
  564.       ruler2[i] = k;
  565.     } else
  566.       exalt[i] = j;
  567.     darg += 3 - (ch1 == '0');
  568.     break;
  569.  
  570. #ifdef INTERPRET
  571.   case 'I':
  572.     if (argc <= 2) {
  573.       ErrorArgc("YI");
  574.       return tcError;
  575.     }
  576.     i = NParseSz(argv[1],
  577.       ch1 == 'A' ? pmAspect : (ch1 == chNull ? pmObject : pmSign));
  578.     j = ch1 == 'A' ? cAspect : (ch1 == chNull ? oNorm : cSign);
  579.     if (!FBetween(i, 1, j)) {
  580.       ErrorValN("YI", i);
  581.       return tcError;
  582.     }
  583.     if (ch1 == 'A' && ch2 == '0')
  584.       ch1 = '0';
  585.     sz = SzPersist(argv[2]);
  586.     switch (ch1) {
  587.     case 'A':    szInteract[i]  = sz; break;
  588.     case '0':    szTherefore[i] = sz; break;
  589.     case chNull: szMindPart[i]  = sz; break;
  590.     case 'C':    szLifeArea[i]  = sz; break;
  591.     case 'v':    szDesire[i]    = sz; break;
  592.     default:     szDesc[i]      = sz;
  593.     }
  594.     darg += 2;
  595.     break;
  596. #endif
  597.  
  598.   case 'k':
  599.     if (argc <= 2 + 2*(ch1 == 'C')) {
  600.       ErrorArgc("Yk");
  601.       return tcError;
  602.     }
  603.     if (ch1 == 'C') {
  604.       kElemA[eFir] = NParseSz(argv[1], pmColor) & 15;
  605.       kElemA[eEar] = NParseSz(argv[2], pmColor) & 15;
  606.       kElemA[eAir] = NParseSz(argv[3], pmColor) & 15;
  607.       kElemA[eWat] = NParseSz(argv[4], pmColor) & 15;
  608.       darg += 4;
  609.       break;
  610.     }
  611.     k = ch1 == 'A' ? pmAspect : 0;
  612.     i = NParseSz(argv[1], k); j = NParseSz(argv[2], k);
  613.     k = ch1 == 'A' ? cAspect : (ch1 == '0' ? 7 : 8);
  614.     if (!FBetween(i, ch1 != chNull, k)) {
  615.       ErrorValN("Yk", i);
  616.       return tcError;
  617.     }
  618.     if (!FBetween(j, ch1 != chNull, k) || j < i) {
  619.       ErrorValN("Yk", j);
  620.       return tcError;
  621.     }
  622.     if (argc <= 3+j-i) {
  623.       ErrorArgc("Yk");
  624.       return tcError;
  625.     }
  626.     lpn = ch1 == 'A' ? kAspA : (ch1 == '0' ? kRainbowA : kMainA);
  627.     for (k = i; k <= j; k++)
  628.       lpn[k] = NParseSz(argv[3+k-i], pmColor) & 15;
  629.     darg += 3+j-i;
  630.     break;
  631.  
  632.   case 'F':
  633.     if (argc <= 8) {
  634.       ErrorArgc("YF");
  635.       return tcError;
  636.     }
  637.     i = NParseSz(argv[1], pmObject);
  638.     if (!FItem(i)) {
  639.       ErrorValN("YF", i);
  640.       return tcError;
  641.     }
  642.     r = Mod((real)(atoi(argv[2]) +
  643.       (NParseSz(argv[3], pmSign)-1)*30) + atof(argv[4])/60.0);
  644.     if (!FCusp(i))
  645.       planet[i] = r;
  646.     else {
  647.       j = Mod12(i-(cuspLo-1)+6);
  648.       if (FBetween(i, cuspLo-1+4, cuspLo-1+9)) {
  649.         chouse[i-(cuspLo-1)] = r;
  650.         chouse[j] = Mod(r + rDegHalf);
  651.       } else {
  652.         planet[i] = r;
  653.         planet[cuspLo-1+j] = Mod(r + rDegHalf);
  654.       }
  655.     }
  656.     j = atoi(argv[5]);
  657.     r = (j < 0 ? -1.0 : 1.0)*((real)abs(j) + atof(argv[6])/60.0);
  658.     planetalt[i] = Mod((r + rDegQuad) * 2.0) / 2.0 - rDegQuad;
  659.     ret[i] = RFromD(atof(argv[7]));
  660.     if (i <= oNorm)
  661.       SphToRec(atof(argv[8]), planet[i], planetalt[i],
  662.         &spacex[i], &spacey[i], &spacez[i]);
  663.     MM = -1;
  664.     darg += 8;
  665.     break;
  666.  
  667. #ifdef GRAPH
  668.   case 'X':
  669.     return NProcessSwitchesRareX(argc, argv, pos+1);
  670. #endif
  671.  
  672.   default:
  673.     ErrorSwitch(argv[0]);
  674.     return tcError;
  675.   }
  676.   return darg;    /* Return the value to be added to argc. */
  677. }
  678.  
  679.  
  680. /* Process a command switch line passed to the program. Read each entry in */
  681. /* the argument list and set all the program modes and charts to display.  */
  682.  
  683. bool FProcessSwitches(argc, argv)
  684. int argc;
  685. char **argv;
  686. {
  687.   int ich, i, j;
  688.   bool fNot, fOr, fAnd;
  689.   real rT;
  690.   char ch1, ch2, *pch;
  691.   CI ci;
  692.  
  693.   argc--; argv++;
  694.   while (argc) {
  695.     ch1 = argv[0][0];
  696.     fNot = fOr = fAnd = fFalse;
  697.     switch (ch1) {
  698.     case '=': fOr  = fTrue; break;
  699.     case '_': fAnd = fTrue; break;
  700.     case ':':               break;
  701.     default:  fNot = fTrue; break;
  702.     }
  703.     ich = 1 + FChSwitch(argv[0][0]);    /* Leading dash? */
  704.     ch1 = argv[0][ich];
  705.     ch2 = ch1 == chNull ? chNull : argv[0][ich+1];
  706.     switch (argv[0][ich-1]) {
  707.  
  708.     case 'H':
  709.       if (ch1 == 'c')
  710.         SwitchF(us.fCredit);
  711.       else if (ch1 == 'Y')
  712.         SwitchF(us.fSwitchRare);
  713. #ifdef ISG
  714.       else if (ch1 == 'X')
  715.         SwitchF(us.fKeyGraph);
  716. #endif
  717.       else if (ch1 == 'C')
  718.         SwitchF(us.fSign);
  719.       else if (ch1 == 'O')
  720.         SwitchF(us.fObject);
  721.       else if (ch1 == 'A')
  722.         SwitchF(us.fAspect);
  723.       else if (ch1 == 'F')
  724.         SwitchF(us.fConstel);
  725.       else if (ch1 == 'S')
  726.         SwitchF(us.fOrbitData);
  727.       else if (ch1 == 'I')
  728.         SwitchF(us.fMeaning);
  729.       else if (ch1 == 'e') {
  730.         SwitchF(us.fCredit); SwitchF(us.fSwitch); SwitchF(us.fSwitchRare);
  731.         SwitchF(us.fKeyGraph); SwitchF(us.fSign); SwitchF(us.fObject);
  732.         SwitchF(us.fAspect); SwitchF(us.fConstel); SwitchF(us.fOrbitData);
  733.         SwitchF(us.fMeaning);
  734.       } else
  735.         SwitchF(us.fSwitch);
  736.       break;
  737.  
  738.     case 'Q':
  739.       if (ch1 == '0')
  740.         SwitchF(us.fLoopInit);
  741.       SwitchF(us.fLoop);
  742.       break;
  743.  
  744.     case 'M':
  745.       i = (ch1 == '0');
  746.       if (argc <= 1+i) {
  747.         ErrorArgc("M");
  748.         return fFalse;
  749.       }
  750.       j = atoi(argv[1]);
  751.       if (!FValidMacro(j)) {
  752.         ErrorValN("M", j);
  753.         return fFalse;
  754.       }
  755.       j--;
  756.       if (i)
  757.         szMacro[j] = SzPersist(argv[2]);
  758.       else
  759.         FProcessCommandLine(szMacro[j]);
  760.       argc -= 1+i; argv += 1+i;
  761.       break;
  762.  
  763.     case 'Y':
  764.       i = NProcessSwitchesRare(argc, argv, ich, fOr, fAnd, fNot);
  765.       if (i < 0)
  766.         return fFalse;
  767.       argc -= i; argv += i;
  768.       break;
  769.  
  770.     /* Switches which determine the type of chart to display: */
  771.  
  772.     case 'v':
  773.       if (ch1 == '0')
  774.         SwitchF(us.fVelocity);
  775.       SwitchF(us.fListing);
  776.       break;
  777.  
  778.     case 'w':
  779.       if (ch1 == '0')
  780.         SwitchF(us.fWheelReverse);
  781.       if (argc > 1 && (i = atoi(argv[1]))) {
  782.         argc--; argv++;
  783.         if (!FValidWheel(i)) {
  784.           ErrorValN("w", i);
  785.           return fFalse;
  786.         }
  787.         us.nWheelRows = i;
  788.       }
  789.       SwitchF(us.fWheel);
  790.       break;
  791.  
  792.     case 'g':
  793.       if (ch1 == '0' || ch2 == '0')
  794.         SwitchF(us.fGridConfig);
  795.       if (ch1 == 'a')
  796.         SwitchF(us.fAppSep);
  797.       else if (ch1 == 'p')
  798.         SwitchF(us.fParallel);
  799. #ifdef X11
  800.       else if (ch1 == 'e') {
  801.         if (argc <= 1) {
  802.           ErrorArgc("geometry");
  803.           return fFalse;
  804.         }
  805.         gs.xWin = atoi(argv[1]);
  806.         if (argc > 2 && (gs.yWin = atoi(argv[2]))) {
  807.           argc--; argv++;
  808.         } else
  809.           gs.yWin = gs.xWin;
  810.         if (!FValidGraphx(gs.xWin)) {
  811.           ErrorValN("geometry", gs.xWin);
  812.           return fFalse;
  813.         }
  814.         if (!FValidGraphy(gs.yWin)) {
  815.           ErrorValN("geometry", gs.yWin);
  816.           return fFalse;
  817.         }
  818.         argc--; argv++;
  819.         break;
  820.       }
  821. #endif
  822.       SwitchF(us.fGrid);
  823.       break;
  824.  
  825.     case 'a':
  826.       SwitchF(us.fAspList);
  827.       if (ch1 == '0') {
  828.         SwitchF(us.fAspSummary);
  829.         ch1 = ch2;
  830.       }
  831.       if (ch1 == 'a')
  832.         SwitchF(us.fAppSep);
  833.       else if (ch1 == 'p')
  834.         SwitchF(us.fParallel);
  835.       break;
  836.  
  837.     case 'm':
  838.       if (ch1 == '0' || ch2 == '0')
  839.         SwitchF(us.fMidSummary);
  840.       if (ch1 == 'a')
  841.         SwitchF(us.fMidAspect);
  842.       SwitchF(us.fMidpoint);
  843.       break;
  844.  
  845.     case 'Z':
  846.       if (ch1 == '0')
  847.         SwitchF(us.fPrimeVert);
  848.       else if (ch1 == 'd')
  849.         SwitchF(us.fHorizonSearch);
  850.       SwitchF(us.fHorizon);
  851.       break;
  852.  
  853.     case 'S':
  854.       SwitchF(us.fOrbit);
  855.       break;
  856.  
  857.     case 'l':
  858.       if (ch1 == '0')
  859.         SwitchF(us.fSectorApprox);
  860.       SwitchF(us.fSector);
  861.       break;
  862.  
  863.     case 'j':
  864.       if (ch1 == '0')
  865.         SwitchF(us.fInfluenceSign);
  866.       SwitchF(us.fInfluence);
  867.       break;
  868.  
  869.     case 'L':
  870.       if (ch1 == '0')
  871.         SwitchF(us.fLatitudeCross);
  872.       if (argc > 1 && (i = atoi(argv[1]))) {
  873.         argc--; argv++;
  874.         if (!FValidAstrograph(i)) {
  875.           ErrorValN("L", i);
  876.           return fFalse;
  877.         }
  878.         us.nAstroGraphStep = i;
  879.       }
  880.       SwitchF(us.fAstroGraph);
  881.       break;
  882.  
  883.     case 'K':
  884.       if (ch1 == 'y')
  885.         SwitchF(us.fCalendarYear);
  886.       SwitchF(us.fCalendar);
  887.       break;
  888.  
  889.     case 'd':
  890.       if (ch1 == 'p') {
  891.         us.fSolarArc = (ch2 == '0');
  892.         if (us.fSolarArc)
  893.           ch2 = argv[0][ich++ + 1];
  894.         i = (ch2 == 'y') + 2*(ch2 == 'Y');
  895. #ifdef TIME
  896.         j = i < 2 && (argv[0][ich+i+1] == 'n');
  897. #else
  898.         j = fFalse;
  899. #endif
  900.         if (!j && argc <= 2-(i&1)) {
  901.           ErrorArgc("dp");
  902.           return fFalse;
  903.         }
  904.         is.fProgress = us.fInDayMonth = fTrue;
  905.         DstT = us.dstDef; ZonT = us.zonDef;
  906.         LonT = us.lonDef; LatT = us.latDef;
  907. #ifdef TIME
  908.         if (j)
  909.           GetTimeNow(&MonT, &DayT, &YeaT, &TimT, ZonT-DstT);
  910. #endif
  911.         if (i) {
  912.           MonT = 0;
  913.           if (!j)
  914.             YeaT = NParseSz(argv[1], pmYea);
  915.           us.nEphemYears = i == 2 ? atoi(argv[2]) : 1;
  916.         } else {
  917.           if (!j) {
  918.             MonT = NParseSz(argv[1], pmMon);
  919.             YeaT = NParseSz(argv[2], pmYea);
  920.             if (!FValidMon(MonT)) {
  921.               ErrorValN("dp", MonT);
  922.               return fFalse;
  923.             }
  924.           }
  925.         }
  926.         if (!FValidYea(YeaT)) {
  927.           ErrorValN("dp", YeaT);
  928.           return fFalse;
  929.         }
  930.         if (!j) {
  931.           i = 2-(i&1);
  932.           argc -= i; argv += i;
  933.         }
  934.       } else if (ch1 == 'm' || ch1 == 'y' || ch1 == 'Y') {
  935.         if (ch1 == 'y')
  936.           us.nEphemYears = 1;
  937.         else if (ch1 == 'Y') {
  938.           if (argc <= 1) {
  939.             ErrorArgc("dY");
  940.             return fFalse;
  941.           }
  942.           i = atoi(argv[1]);
  943.           if (i < 1) {
  944.             ErrorValN("dY", i);
  945.             return fFalse;
  946.           }
  947.           us.nEphemYears = i;
  948.           argc--; argv++;
  949.         }
  950.         SwitchF(us.fInDayMonth);
  951.         MonT = (ch1 == 'm');
  952.       }
  953. #ifdef X11
  954.       else if (ch1 == 'i') {    /* -display switch for X */
  955.         if (argc <= 1) {
  956.           ErrorArgc("display");
  957.           return fFalse;
  958.         }
  959.         gs.szDisplay = SzPersist(argv[1]);
  960.         argc--; argv++;
  961.         break;
  962.       }
  963. #endif
  964.       else if (argc > 1 && (i = atoi(argv[1]))) {
  965.         if (!FValidDivision(i)) {
  966.           ErrorValN("d", i);
  967.           return fFalse;
  968.         }
  969.         us.nDivision = i;
  970.         argc--; argv++;
  971.       }
  972.       SwitchF(us.fInDay);
  973.       break;
  974.  
  975.     case 'D':
  976.       SwitchF(us.fInDayInf);
  977.       break;
  978.  
  979.     case 'E':
  980.       if (ch1 == 'Y' && argc <= 1) {
  981.         ErrorArgc("E");
  982.         return fFalse;
  983.       }
  984.       SwitchF(us.fEphemeris);
  985.       if (ch1 == 'y')
  986.         us.nEphemYears = us.fEphemeris ? 1 : 0;
  987.       else if (ch1 == 'Y') {
  988.         i = atoi(argv[1]);
  989.         if (i < 1) {
  990.           ErrorValN("EY", i);
  991.           return fFalse;
  992.         }
  993.         us.nEphemYears = i;
  994.       }
  995.       break;
  996.  
  997.     case 'e':
  998.       SwitchF(us.fListing); SwitchF(us.fWheel);
  999.       SwitchF(us.fGrid); SwitchF(us.fAspList); SwitchF(us.fMidpoint);
  1000.       SwitchF(us.fHorizon); SwitchF(us.fOrbit); SwitchF(us.fSector);
  1001.       SwitchF(us.fCalendar); SwitchF(us.fInfluence); SwitchF(us.fAstroGraph);
  1002.       SwitchF(us.fInDay); SwitchF(us.fInDayInf);
  1003.       SwitchF(us.fEphemeris);
  1004.       SwitchF(us.fGridConfig); SwitchF(us.fInfluenceSign);
  1005.       SwitchF(us.fLatitudeCross);
  1006.       break;
  1007.  
  1008.     case 't':
  1009.       SwitchF(us.fTransit);
  1010.       ZonT = us.zonDef; DstT = us.dstDef; LonT = us.lonDef; LatT = us.latDef;
  1011.       if (ch1 == 'p') {
  1012.         us.fSolarArc = (ch2 == '0');
  1013.         if (us.fSolarArc)
  1014.           ich++;
  1015.         is.fProgress = fTrue;
  1016.         ch1 = argv[0][++ich];
  1017.       }
  1018.       if (ch1 == 'r') {
  1019.         is.fReturn = fTrue;
  1020.         ch1 = argv[0][++ich];
  1021.       }
  1022.       if (i = (ch1 == 'y') + 2*(ch1 == 'Y'))
  1023.         ch1 = argv[0][++ich];
  1024. #ifdef TIME
  1025.       if (ch1 == 'n') {
  1026.         GetTimeNow(&MonT, &DayT, &YeaT, &TimT, ZonT-DstT);
  1027.         if (i == 1)
  1028.           MonT = 0;
  1029.         else if (i > 1) {
  1030.           MonT = -1; DayT = NParseSz(argv[1], pmDay);
  1031.         }
  1032.         break;
  1033.       }
  1034. #endif
  1035.       if (argc <= 2 - (i & 1)) {
  1036.         ErrorArgc("t");
  1037.         return fFalse;
  1038.       }
  1039.       if (i) {
  1040.         if (i == 1)
  1041.           MonT = 0;
  1042.         else {
  1043.           MonT = -1; DayT = NParseSz(argv[2], pmDay);
  1044.         }
  1045.       } else {
  1046.         MonT = NParseSz(argv[1], pmMon);
  1047.         if (!FValidMon(MonT)) {
  1048.           ErrorValN("t", MonT);
  1049.           return fFalse;
  1050.         }
  1051.       }
  1052.       YeaT = NParseSz(argv[2 - (i > 0)], pmYea);
  1053.       argc -= 2 - (i & 1); argv += 2 - (i & 1);
  1054.       break;
  1055.  
  1056.     case 'T':
  1057.       SwitchF(us.fTransitInf);
  1058.       ZonT = us.zonDef; DstT = us.dstDef; LonT = us.lonDef; LatT = us.latDef;
  1059.       if (ch1 == 'p') {
  1060.         is.fProgress = fTrue;
  1061.         ch1 = argv[0][++ich];
  1062.       }
  1063.       if (ch1 == 'r') {
  1064.         is.fReturn = fTrue;
  1065.         ch1 = argv[0][++ich];
  1066.       }
  1067. #ifdef TIME
  1068.       if (ch1 == 'n') {
  1069.         GetTimeNow(&MonT, &DayT, &YeaT, &TimT, ZonT-DstT);
  1070.         break;
  1071.       }
  1072. #endif
  1073.       if (argc <= 3) {
  1074.         ErrorArgc("T");
  1075.         return fFalse;
  1076.       }
  1077.       MonT = NParseSz(argv[1], pmMon);
  1078.       DayT = NParseSz(argv[2], pmDay);
  1079.       YeaT = NParseSz(argv[3], pmYea);
  1080.       if (!FValidMon(MonT)) {
  1081.         ErrorValN("T", MonT);
  1082.         return fFalse;
  1083.       } else if (!FValidDay(DayT, MonT, YeaT)) {
  1084.         ErrorValN("T", DayT);
  1085.         return fFalse;
  1086.       } else if (!FValidYea(YeaT)) {
  1087.         ErrorValN("T", YeaT);
  1088.         return fFalse;
  1089.       }
  1090.       argc -= 3; argv += 3;
  1091.       break;
  1092.  
  1093. #ifdef ARABIC
  1094.     case 'P':
  1095.       if (argc > 1 && (i = atoi(argv[1]))) {
  1096.         argc--; argv++;
  1097.         if (!FValidPart(i)) {
  1098.           ErrorValN("P", i);
  1099.           return fFalse;
  1100.         }
  1101.         us.nArabicParts = i;
  1102.       }
  1103.       if (ch1 == 'z' || ch1 == 'n' || ch1 == 'f') {
  1104.         us.nArabic = ch1;
  1105.         ch1 = ch2;
  1106.       } else
  1107.         SwitchF(us.nArabic);
  1108.       if (ch1 == '0')
  1109.         SwitchF(us.fArabicFlip);
  1110.       break;
  1111. #endif
  1112.  
  1113. #ifdef INTERPRET
  1114.     case 'I':
  1115.       if (argc > 1 && (i = atoi(argv[1]))) {
  1116.         argc--; argv++;
  1117.         if (!FValidScreen(i)) {
  1118.           ErrorValN("I", i);
  1119.           return fFalse;
  1120.         }
  1121.         us.nScreenWidth = i;
  1122.       }
  1123.       SwitchF(us.fInterpret);
  1124.       break;
  1125. #endif
  1126.  
  1127.     /* Switches which affect how the chart parameters are obtained: */
  1128.  
  1129. #ifdef TIME
  1130.     case 'n':
  1131.       FInputData(szNowCore);
  1132.       if (ch1 == 'd')
  1133.         TT = 0.0;
  1134.       else if (ch1 == 'm') {
  1135.         DD = 1; TT = 0.0;
  1136.       } else if (ch1 == 'y') {
  1137.         MM = DD = 1; TT = 0.0;
  1138.       }
  1139.       break;
  1140. #endif
  1141.  
  1142.     case 'z':
  1143.       if (ch1 == '0') {
  1144.         if (argc <= 1 || RParseSz(argv[1], pmZon) == rLarge) {
  1145.           i = us.dstDef != 0.0;
  1146.           SwitchF(i);
  1147.           SS = us.dstDef = i ? 1.0 : 0.0;
  1148.         } else {
  1149.           SS = us.dstDef = RParseSz(argv[1], pmZon);
  1150.           if (!FValidDst(us.dstDef)) {
  1151.             ErrorValR("z0", us.dstDef);
  1152.             return fFalse;
  1153.           }
  1154.           argc--; argv++;
  1155.         }
  1156.         break;
  1157.       } else if (ch1 == 'l') {
  1158.         if (argc <= 2) {
  1159.           ErrorArgc("zl");
  1160.           return fFalse;
  1161.         }
  1162.         OO = us.lonDef = RParseSz(argv[1], pmLon);
  1163.         AA = us.latDef = RParseSz(argv[2], pmLat);
  1164.         if (!FValidLon(us.lonDef)) {
  1165.           ErrorValR("zl", us.lonDef);
  1166.           return fFalse;
  1167.         } else if (!FValidLat(us.latDef)) {
  1168.           ErrorValR("zl", us.latDef);
  1169.           return fFalse;
  1170.         }
  1171.         argc -= 2; argv += 2;
  1172.         break;
  1173.       } else if (ch1 == 't') {
  1174.         if (argc <= 1) {
  1175.           ErrorArgc("zt");
  1176.           return fFalse;
  1177.         }
  1178.         rT = RParseSz(argv[1], pmTim);
  1179.         if (!FValidTim(rT)) {
  1180.           ErrorValR("zt", rT);
  1181.           return fFalse;
  1182.         }
  1183.         TT = rT;
  1184.         argc--; argv++;
  1185.         break;
  1186.       } else if (ch1 == 'd') {
  1187.         if (argc <= 1) {
  1188.           ErrorArgc("zd");
  1189.           return fFalse;
  1190.         }
  1191.         i = NParseSz(argv[1], pmDay);
  1192.         if (!FValidDay(i, MM, YY)) {
  1193.           ErrorValN("zd", i);
  1194.           return fFalse;
  1195.         }
  1196.         DD = i;
  1197.         argc--; argv++;
  1198.         break;
  1199.       } else if (ch1 == 'i') {
  1200.         if (argc <= 2) {
  1201.           ErrorArgc("zi");
  1202.           return fFalse;
  1203.         }
  1204.         ciCore.nam = SzPersist(argv[1]);
  1205.         ciCore.loc = SzPersist(argv[2]);
  1206.         argc -= 2; argv += 2;
  1207.         break;
  1208.       }
  1209.       if (argc <= 1 || RParseSz(argv[1], pmZon) == rLarge)
  1210.         ZZ -= 1.0;
  1211.       else {
  1212.         ZZ = us.zonDef = RParseSz(argv[1], pmZon);
  1213.         if (!FValidZon(us.zonDef)) {
  1214.           ErrorValR("z", us.zonDef);
  1215.           return fFalse;
  1216.         }
  1217.         argc--; argv++;
  1218.       }
  1219.       break;
  1220.  
  1221.     case 'q':
  1222.       i = (ch1 == 'y' || ch1 == 'j') + 2*(ch1 == 'm') + 3*(ch1 == 'd') +
  1223.         4*(ch1 == chNull) + 7*(ch1 == 'a') + 8*(ch1 == 'b');
  1224.       if (argc <= i) {
  1225.         ErrorArgc("q");
  1226.         return fFalse;
  1227.       }
  1228.       is.fHaveInfo = fTrue;
  1229.       if (ch1 == 'j') {
  1230.         is.JD = atof(argv[1])+rRound;
  1231.         TT = RFract(is.JD);
  1232.         JulianToMdy(is.JD-TT, &MM, &DD, &YY);
  1233.         TT = DegToDec(TT * 24.0);
  1234.         SS = ZZ = 0.0; OO = us.lonDef; AA = us.latDef;
  1235.       } else {
  1236.         MM = i > 1 ? NParseSz(argv[1], pmMon) : 1;
  1237.         DD = i > 2 ? NParseSz(argv[2], pmDay) : 1;
  1238.         YY = NParseSz(argv[3-(i<3)-(i<2)], pmYea);
  1239.         TT = i > 3 ? RParseSz(argv[4], pmTim) : (i < 3 ? 0.0 : 12.0);
  1240.         SS = i > 7 ? RParseSz(argv[5], pmDst) : (i > 6 ? 0.0 : us.dstDef);
  1241.         ZZ = i > 6 ? RParseSz(argv[5 + (i > 7)], pmZon) : us.zonDef;
  1242.         OO = i > 6 ? RParseSz(argv[6 + (i > 7)], pmLon) : us.lonDef;
  1243.         AA = i > 6 ? RParseSz(argv[7 + (i > 7)], pmLat) : us.latDef;
  1244.         if (!FValidMon(MM)) {
  1245.           ErrorValN("q", MM);
  1246.           return fFalse;
  1247.         } else if (!FValidDay(DD, MM, YY)) {
  1248.           ErrorValN("q", DD);
  1249.           return fFalse;
  1250.         } else if (!FValidYea(YY)) {
  1251.           ErrorValN("q", YY);
  1252.           return fFalse;
  1253.         } else if (!FValidTim(TT)) {
  1254.           ErrorValR("q", TT);
  1255.           return fFalse;
  1256.         } else if (!FValidDst(SS)) {
  1257.           ErrorValR("q", SS);
  1258.           return fFalse;
  1259.         } else if (!FValidZon(ZZ)) {
  1260.           ErrorValR("a", ZZ);
  1261.           return fFalse;
  1262.         } else if (!FValidLon(OO)) {
  1263.           ErrorValR("a", OO);
  1264.           return fFalse;
  1265.         } else if (!FValidLat(AA)) {
  1266.           ErrorValR("a", AA);
  1267.           return fFalse;
  1268.         }
  1269.       }
  1270.       argc -= i; argv += i;
  1271.       break;
  1272.  
  1273.     case 'i':
  1274.       if (us.fNoRead) {
  1275.         ErrorArgv("i");
  1276.         return tcError;
  1277.       }
  1278.       if (argc <= 1) {
  1279.         ErrorArgc("i");
  1280.         return fFalse;
  1281.       }
  1282.       ci = ciCore;
  1283.       if (!FInputData(argv[1]))
  1284.         return fFalse;
  1285.       if (ch1 == '2') {
  1286.         ciTwin = ciCore;
  1287.         ciCore = ci;
  1288.       } else if (ch1 == '3') {
  1289.         ciThre = ciCore;
  1290.         ciCore = ci;
  1291.       } else if (ch1 == '4') {
  1292.         ciFour = ciCore;
  1293.         ciCore = ci;
  1294.       }
  1295.       argc--; argv++;
  1296.       break;
  1297.  
  1298.     case '>':
  1299.       ch1 = 's';
  1300.       /* Fall through */
  1301.  
  1302.     case 'o':
  1303.       if (us.fNoWrite) {
  1304.         ErrorArgv("o");
  1305.         return tcError;
  1306.       }
  1307.       if (argc <= 1) {
  1308.         ErrorArgc("o");
  1309.         return fFalse;
  1310.       }
  1311.       if (ch1 == 's') {
  1312.         is.szFileScreen = SzPersist(argv[1]);
  1313.         argc--; argv++;
  1314.         break;
  1315.       } else if (ch1 == '0')
  1316.         SwitchF(us.fWritePos);
  1317.       SwitchF(us.fWriteFile);
  1318.       is.szFileOut = SzPersist(argv[1]);
  1319.       if (is.fSzPersist) {
  1320.         is.rgszComment = argv;
  1321.         do {
  1322.           argc--; argv++;
  1323.           is.cszComment++;
  1324.         } while (argc > 1 && !FChSwitch(argv[1][0]));
  1325.       }
  1326.       break;
  1327.  
  1328.     /* Switches which affect what information is used in a chart: */
  1329.  
  1330.     case 'R':
  1331.       if (ch1 == 'A') {
  1332.         while (argc > 1 && (i = NParseSz(argv[1], pmAspect)))
  1333.           if (!FAspect(i)) {
  1334.             ErrorValN("RA", i);
  1335.             return fFalse;
  1336.           } else {
  1337.             rAspOrb[i] = -rDegHalf;
  1338.             argc--; argv++;
  1339.           }
  1340.         break;
  1341.       }
  1342.       if (ch1 == 'T') {
  1343.         pch = (char *)ignore2;
  1344.         ch1 = argv[0][++ich];
  1345.       } else
  1346.         pch = (char *)ignore;
  1347.       if (ch1 == '0')
  1348.         for (i = 1; i <= cObj; i++)
  1349.           pch[i] = fTrue;
  1350.       else if (ch1 == '1') {
  1351.         for (i = 1; i <= cObj; i++)
  1352.           pch[i] = fFalse;
  1353.         us.fCusp = us.fUranian = us.nStar = fTrue;
  1354.       } else if (ch1 == 'C')
  1355.         for (i = cuspLo; i <= cuspHi; i++)
  1356.           SwitchF(pch[i]);
  1357.       else if (ch1 == 'u')
  1358.         for (i = uranLo; i <= uranHi; i++)
  1359.           SwitchF(pch[i]);
  1360.       else if (ch1 == 'U')
  1361.         for (i = starLo; i <= starHi; i++)
  1362.           SwitchF(pch[i]);
  1363.       else if (argc <= 1 || (!NParseSz(argv[1], pmObject))) {
  1364.         for (i = oChi; i <= oVes; i++)
  1365.           SwitchF(pch[i]);
  1366.         for (i = oLil; i <= oEP; i++)
  1367.           SwitchF(pch[i]);
  1368.       }
  1369.       while (argc > 1 && (i = NParseSz(argv[1], pmObject)))
  1370.         if (!FItem(i)) {
  1371.           ErrorValN("R", i);
  1372.           return fFalse;
  1373.         } else {
  1374.           SwitchF(pch[i]);
  1375.           argc--; argv++;
  1376.         }
  1377.       break;
  1378.  
  1379.     case 'C':
  1380.       SwitchF(us.fCusp);
  1381.       break;
  1382.  
  1383.     case 'u':
  1384.       SwitchF(us.fUranian);
  1385.       break;
  1386.  
  1387.     case 'U':
  1388.       if (ch1 == 'z' || ch1 == 'l' || ch1 == 'n' || ch1 == 'b')
  1389.         us.nStar = ch1;
  1390.       else
  1391.         SwitchF(us.nStar);
  1392.       break;
  1393.  
  1394.     case 'A':
  1395.       if (ch1 != 'o' && ch1 != 'm' && ch1 != 'd' && ch1 != 'a') {
  1396.         if (argc <= 1) {
  1397.           ErrorArgc("A");
  1398.           return fFalse;
  1399.         }
  1400.         i = NParseSz(argv[1], pmAspect);
  1401.         if (!FValidAspect(i)) {
  1402.           ErrorValN("A", i);
  1403.           return fFalse;
  1404.         }
  1405.         us.nAsp = i;
  1406.         argc--; argv++;
  1407.       } else {
  1408.         if (argc <= 2) {
  1409.           ErrorArgc("A");
  1410.           return fFalse;
  1411.         }
  1412.         i = NParseSz(argv[1], ch1 == 'o' || ch1 == 'a' ? pmAspect : pmObject);
  1413.         if (i < 1 || i > (ch1 == 'o' || ch1 == 'a' ? cAspect : oNorm)) {
  1414.           ErrorValN("A", i);
  1415.           return fFalse;
  1416.         }
  1417.         rT = RParseSz(argv[2], 0);
  1418.         if (rT < -rDegMax || rT > rDegMax) {
  1419.           ErrorValR("A", rT);
  1420.           return fFalse;
  1421.         }
  1422.         if (ch1 == 'o')
  1423.           rAspOrb[i] = rT;
  1424.         else if (ch1 == 'm')
  1425.           rObjOrb[i] = rT;
  1426.         else if (ch1 == 'd')
  1427.           rObjAdd[i] = rT;
  1428.         else
  1429.           rAspAngle[i] = rT;
  1430.         argc -= 2; argv += 2;
  1431.       }
  1432.       break;
  1433.  
  1434.     /* Switches which affect how a chart is computed: */
  1435.  
  1436.     case 'b':
  1437.       if (ch1 == '0')
  1438.         SwitchF(us.fSeconds);
  1439.       else if (ch1 == 'a')
  1440.         SwitchF(us.fPlacalcAst);
  1441. #ifdef PLACALC
  1442.       SwitchF(us.fPlacalc);
  1443. #endif
  1444.       is.fSeconds = us.fSeconds;
  1445.       break;
  1446.  
  1447.     case 'c':
  1448.       if (argc <= 1) {
  1449.         ErrorArgc("c");
  1450.         return fFalse;
  1451.       }
  1452.       i = NParseSz(argv[1], pmSystem);
  1453.       if (!FValidSystem(i)) {
  1454.         ErrorValN("c", i);
  1455.         return fFalse;
  1456.       }
  1457.       us.nHouseSystem = i;
  1458.       argc--; argv++;
  1459.       break;
  1460.  
  1461.     case 's':
  1462.       if (argc > 1 && ((rT = atof(argv[1])) != 0.0 || FNumCh(argv[1][0]))) {
  1463.         if (!FValidOffset(rT)) {
  1464.           ErrorValR("s", rT);
  1465.           return fFalse;
  1466.         }
  1467.         argc--; argv++;
  1468.         us.rZodiacOffset = rT;
  1469.       }
  1470.       if (ch1 == 'r')
  1471.         SwitchF(us.fEquator);
  1472.       else if (ch1 == 'h')
  1473.         us.nDegForm = 1;
  1474.       else if (ch1 == 'd')
  1475.         us.nDegForm = 2;
  1476.       else if (ch1 == 'z')
  1477.         us.nDegForm = 0;
  1478.       else
  1479.         SwitchF(us.fSidereal);
  1480.       break;
  1481.  
  1482.     case 'h':
  1483.       if (argc > 1 && (i = NParseSz(argv[1], pmObject))) {
  1484.         argc--; argv++;
  1485.       } else
  1486.         i = FSwitchF(us.objCenter != 0);
  1487.       if (!FValidCenter(i)) {
  1488.         ErrorValN("h", i);
  1489.         return fFalse;
  1490.       }
  1491.       us.objCenter = i;
  1492.       break;
  1493.  
  1494.     case 'p':
  1495.       if (fAnd) {
  1496.         us.fProgress = fFalse;
  1497.         break;
  1498.       }
  1499.       us.fSolarArc = (ch1 == '0');
  1500.       if (us.fSolarArc)
  1501.         ch1 = (argv[0][++ich]);
  1502.       us.fProgress = fTrue;
  1503. #ifdef TIME
  1504.       if (ch1 == 'n') {
  1505.         GetTimeNow(&Mon, &Day, &Yea, &Tim, us.zonDef - us.dstDef);
  1506.         is.JDp = MdytszToJulian(Mon, Day, Yea, Tim, us.dstDef, us.zonDef);
  1507.         break;
  1508.       }
  1509. #endif
  1510.       if (ch1 == 'd') {
  1511.         if (argc <= 1) {
  1512.           ErrorArgc("pd");
  1513.           return fFalse;
  1514.         }
  1515.         us.rProgDay = atof(argv[1]);
  1516.         if (us.rProgDay == 0.0) {
  1517.           ErrorValR("pd", us.rProgDay);
  1518.           return fFalse;
  1519.         }
  1520.         argc--; argv++;
  1521.         break;
  1522.       }
  1523.       if (argc <= 3) {
  1524.         ErrorArgc("p");
  1525.         return fFalse;
  1526.       }
  1527.       Mon = NParseSz(argv[1], pmMon);
  1528.       Day = NParseSz(argv[2], pmDay);
  1529.       Yea = NParseSz(argv[3], pmYea);
  1530.       if (!FValidMon(Mon)) {
  1531.         ErrorValN("p", Mon);
  1532.         return fFalse;
  1533.       } else if (!FValidDay(Day, Mon, Yea)) {
  1534.         ErrorValN("p", Day);
  1535.         return fFalse;
  1536.       } else if (!FValidYea(Yea)) {
  1537.         ErrorValN("p", Yea);
  1538.         return fFalse;
  1539.       }
  1540.       is.JDp = MdytszToJulian(Mon, Day, Yea, 0.0, us.dstDef, us.zonDef);
  1541.       argc -= 3; argv += 3;
  1542.       break;
  1543.  
  1544.     case 'x':
  1545.       if (argc <= 1) {
  1546.         ErrorArgc("x");
  1547.         return fFalse;
  1548.       }
  1549.       i = atoi(argv[1]);
  1550.       if (!FValidHarmonic(i)) {
  1551.         ErrorValN("x", i);
  1552.         return fFalse;
  1553.       }
  1554.       us.nHarmonic = i;
  1555.       argc--; argv++;
  1556.       break;
  1557.  
  1558.     case '1':
  1559.       if (argc > 1 && (i = NParseSz(argv[1], pmObject))) {
  1560.         argc--; argv++;
  1561.       } else
  1562.         i = oSun;
  1563.       if (!FItem(i)) {
  1564.         ErrorValN("1", i);
  1565.         return fFalse;
  1566.       }
  1567.       us.objOnAsc = fAnd ? 0 : i;
  1568.       break;
  1569.  
  1570.     case '2':
  1571.       if (argc > 1 && (i = NParseSz(argv[1], pmObject))) {
  1572.         argc--; argv++;
  1573.       } else
  1574.         i = oSun;
  1575.       if (!FItem(i)) {
  1576.         ErrorValN("2", i);
  1577.         return fFalse;
  1578.       }
  1579.       us.objOnAsc = fAnd ? 0 : -i;
  1580.       break;
  1581.  
  1582.     case '3':
  1583.       SwitchF(us.fDecan);
  1584.       break;
  1585.  
  1586.     case 'f':
  1587.       SwitchF(us.fFlip);
  1588.       break;
  1589.  
  1590.     case 'G':
  1591.       SwitchF(us.fGeodetic);
  1592.       break;
  1593.  
  1594.     case 'F':
  1595.       if (argc <= 3) {
  1596.         ErrorArgc("F");
  1597.         return fFalse;
  1598.       }
  1599.       i = NParseSz(argv[1], pmObject);
  1600.       if (!FItem(i)) {
  1601.         ErrorValN("F", i);
  1602.         return fFalse;
  1603.       }
  1604.       force[i] = (NParseSz(argv[2], pmSign)-1.0)*30.0+DecToDeg(atof(argv[3]));
  1605.       if (force[i] < 0.0 || force[i] >= rDegMax) {
  1606.         ErrorValR("F", force[i]);
  1607.         return fFalse;
  1608.       } else
  1609.         force[i] += rDegMax;
  1610.       argc -= 3; argv += 3;
  1611.       break;
  1612.  
  1613.     case '+':
  1614.       if (argc > 1 && (i = atoi(argv[1])) != 0) {
  1615.         argc--; argv++;
  1616.       } else
  1617.         i = 1;
  1618.       us.dayDelta += i * (ch1 == 'y' ? 365 : (ch1 == 'm' ? 30 : 1));
  1619.       break;
  1620.  
  1621.     case chNull:
  1622.       if (ich <= 1)
  1623.         break;
  1624.       /* Fall thorugh */
  1625.  
  1626.     case '-':
  1627.       if (argc > 1 && (i = atoi(argv[1])) != 0) {
  1628.         argc--; argv++;
  1629.       } else
  1630.         i = 1;
  1631.       us.dayDelta -= i * (ch1 == 'y' ? 365 : (ch1 == 'm' ? 30 : 1));
  1632.       break;
  1633.  
  1634.     /* Switches for relationship and comparison charts: */
  1635.  
  1636.     case 'r':
  1637.       if (fAnd) {
  1638.         us.nRel = 0;
  1639.         break;
  1640.       } else if (FBetween(ch1, '1', '4')) {
  1641.         us.nRel = -(int)(ch1-'1');
  1642.         break;
  1643.       }
  1644.       i = 2 + 2*((ch1 == 'c' || ch1 == 'm') && ch2 == '0');
  1645.       if (argc <= i) {
  1646.         ErrorArgc("r");
  1647.         return fFalse;
  1648.       }
  1649.       if (ch1 == 'c')
  1650.         us.nRel = rcComposite;
  1651.       else if (ch1 == 'm')
  1652.         us.nRel = rcMidpoint;
  1653.       else if (ch1 == 'd')
  1654.         us.nRel = rcDifference;
  1655. #ifdef BIORHYTHM
  1656.       else if (ch1 == 'b')
  1657.         us.nRel = rcBiorhythm;
  1658. #endif
  1659.       else if (ch1 == '0')
  1660.         us.nRel = rcDual;
  1661.       else if (ch1 == 't')
  1662.         us.nRel = rcTransit;
  1663.       else if (ch1 == 'p') {
  1664.         us.nRel = rcProgress;
  1665.         us.fSolarArc = (ch2 == '0');
  1666.       } else
  1667.         us.nRel = rcSynastry;
  1668.       if (!FInputData(argv[2]))
  1669.         return fFalse;
  1670.       ciTwin = ciCore;
  1671.       if (!FInputData(argv[1]))
  1672.         return fFalse;
  1673.       if (i > 2) {
  1674.         us.nRatio1 = atoi(argv[3]);
  1675.         us.nRatio2 = atoi(argv[4]);
  1676.         if (us.nRatio1 == us.nRatio2)
  1677.           us.nRatio1 = us.nRatio2 = 1;
  1678.       }
  1679.       argc -= i; argv += i;
  1680.       break;
  1681.  
  1682. #ifdef TIME
  1683.     case 'y':
  1684.       if (argc <= 1) {
  1685.         ErrorArgc("y");
  1686.         return fFalse;
  1687.       }
  1688.       if (ch1 == 'd')
  1689.         us.nRel = rcDifference;
  1690. #ifdef BIORHYTHM
  1691.       else if (ch1 == 'b')
  1692.         us.nRel = rcBiorhythm;
  1693. #endif
  1694.       else if (ch1 == 't')
  1695.         us.nRel = rcTransit;
  1696.       else if (ch1 == 'p') {
  1697.         us.nRel = rcProgress;
  1698.         us.fSolarArc = (ch2 == '0');
  1699.       } else
  1700.         us.nRel = rcDual;
  1701.       if (!FInputData(szNowCore))
  1702.         return fFalse;
  1703.       ciTwin = ciCore;
  1704.       if (!FInputData(argv[1]))
  1705.         return fFalse;
  1706.       argc--; argv++;
  1707.       break;
  1708. #endif
  1709.  
  1710.     /* Switches to access graphics options: */
  1711.  
  1712.     case 'k':
  1713.       if (ch1 == '1') {
  1714.         us.fAnsiColor = 2;
  1715.         us.fAnsiChar  = 1;
  1716.       } else {
  1717.         if (ch1 != '0')
  1718.           SwitchF(us.fAnsiColor);
  1719.         SwitchF(us.fAnsiChar);
  1720.       }
  1721.       break;
  1722.  
  1723. #ifdef PCG
  1724.     case 'V':
  1725.       if (argc <= 1) {
  1726.         ErrorArgc("V");
  1727.         return fFalse;
  1728.       }
  1729.       i = atoi(argv[1]);
  1730.       if (!FValidTextrows(i)) {
  1731.         ErrorValN("V", i);
  1732.         return fFalse;
  1733.       }
  1734.       gs.nTextRows = i;
  1735.       argc--; argv++;
  1736.       break;
  1737. #endif
  1738.  
  1739. #ifdef GRAPH
  1740.     case 'X':
  1741.       if (us.fNoGraphics) {
  1742.         ErrorArgv("X");
  1743.         return fFalse;
  1744.       }
  1745.       i = NProcessSwitchesX(argc, argv, ich, fOr, fAnd, fNot);
  1746.       if (i < 0)
  1747.         return fFalse;
  1748.       SwitchF2(us.fGraphics);
  1749.       argc -= i; argv += i;
  1750.       break;
  1751.  
  1752. #ifdef WIN
  1753.     case 'W':
  1754.       i = NProcessSwitchesW(argc, argv, ich, fOr, fAnd, fNot);
  1755.       if (i < 0)
  1756.         return fFalse;
  1757.       argc -= i; argv += i;
  1758.       break;
  1759. #endif
  1760. #endif /* GRAPH */
  1761.  
  1762.     case '0':
  1763.       while (ch1 != chNull) {
  1764.         switch (ch1) {
  1765.         case 'o': us.fNoWrite    = fTrue; break;
  1766.         case 'i': us.fNoRead     = fTrue; break;
  1767.         case 'q': us.fNoQuit     = fTrue; break;
  1768.         case 'X': us.fNoGraphics = fTrue; break;
  1769.         }
  1770.         ch1 = (argv[0][++ich]);
  1771.       }
  1772.       break;
  1773.  
  1774.     case ';':    /* The -; switch means don't process the rest of the line. */
  1775.       return fTrue;
  1776.  
  1777.     case '@':    /* The -@ switch is just a system flag indicator no-op. */
  1778.       break;
  1779.  
  1780.     case '.':                /* "-." is usually used to exit the -Q loop. */
  1781.       Terminate(tcForce);
  1782.  
  1783.     case 'B':                /* For no useful reason, -B sounds a beep. */
  1784. #ifndef WIN
  1785.       putchar(chBell);
  1786. #else
  1787.       MessageBeep((UINT)-1);
  1788. #endif
  1789.       break;
  1790.  
  1791.     default:
  1792.       ErrorSwitch(argv[0]);
  1793.       return fFalse;
  1794.     }
  1795.     argc--; argv++;
  1796.   }
  1797.   return fTrue;
  1798. }
  1799.  
  1800.  
  1801. /*
  1802. ******************************************************************************
  1803. ** Main Program.
  1804. ******************************************************************************
  1805. */
  1806.  
  1807. #ifndef WIN
  1808. #ifndef NOMAIN
  1809. /* The main program, the starting point for Astrolog, follows. This routine */
  1810. /* basically consists of a loop, inside which we read a command line, and   */
  1811. /* go process it, before actually calling a routine to do the neat stuff.   */
  1812.  
  1813. #ifdef SWITCHES
  1814. void main(argc, argv)
  1815. int argc;
  1816. char **argv;
  1817. {
  1818. #else
  1819. void main()
  1820. {
  1821.   int argc;
  1822.   char **argv;
  1823. #endif
  1824.   char szCommandLine[cchSzMax], *rgsz[MAXSWITCHES];
  1825.  
  1826.   /* Read in info from the astrolog.dat file. */
  1827.   is.S = stdout;
  1828.   FProcessSwitchFile(DEFAULT_INFOFILE, NULL);
  1829.  
  1830. LBegin:
  1831. #ifdef PCG
  1832.   if (gs.nTextRows > 0) {
  1833.     PcSetTextRows(gs.nTextRows);
  1834.     neg(gs.nTextRows);
  1835.   }
  1836. #endif
  1837.   if (us.fNoSwitches) {                             /* Go prompt for    */
  1838.     argc = NPromptSwitches(szCommandLine, rgsz);    /* switches if we   */
  1839.     argv = rgsz;                                    /* don't have them. */
  1840.   }
  1841.   is.szProgName = argv[0];
  1842.   is.fSzPersist = fTrue;
  1843.   if (FProcessSwitches(argc, argv)) {
  1844.     if (!us.fNoSwitches && us.fLoopInit) {
  1845.       us.fNoSwitches = fTrue;
  1846.       goto LBegin;
  1847.     }
  1848. #ifdef PCG
  1849.     if (gs.nTextRows > 0) {
  1850.       PcSetTextRows(gs.nTextRows);
  1851.       neg(gs.nTextRows);
  1852.     }
  1853. #endif
  1854.     Action();
  1855.   }
  1856.   if (us.fLoop || us.fNoQuit) { /* If -Q in effect loop back and get switch */
  1857.     PrintL2();                  /* info for another chart to display.       */
  1858.     InitVariables();
  1859.     us.fLoop = us.fNoSwitches = fTrue;
  1860.     goto LBegin;
  1861.   }
  1862.   Terminate(tcOK);    /* The only standard place to exit Astrolog is here. */
  1863. }
  1864. #endif /* NOMAIN */
  1865. #endif /* WIN */
  1866.  
  1867. /* astrolog.c */
  1868.